using FytSoa.Application.Analytical.CrmDto;
using FytSoa.Application.Crm;
using FytSoa.Common.Enum;
using FytSoa.Domain.Crm;
using FytSoa.Domain.Sys;
using FytSoa.Sugar;
using Masuit.Tools.Systems;
using Microsoft.AspNetCore.Mvc;
using SqlSugar;

namespace FytSoa.Application.Analytical;

/// <summary>
/// CRM工作台
/// </summary>
[ApiExplorerSettings(GroupName = "v1")]
public class CrmAnalyticalService : IApplicationService
{
    private readonly SugarRepository<CrmCustomer> _customerRepository;
    private readonly SugarRepository<CrmContact> _contactRepository;
    private readonly SugarRepository<CrmProject> _projectRepository;
    private readonly SugarRepository<SysCode> _codeRepository;
    private readonly SugarRepository<CrmContract> _contractRepository;
    private readonly SugarRepository<CrmPayment> _paymentRepository;
    public CrmAnalyticalService(SugarRepository<CrmCustomer> customerRepository
    ,SugarRepository<CrmContact> contactRepository
    ,SugarRepository<CrmProject> projectRepository
    ,SugarRepository<SysCode> codeRepository
    ,SugarRepository<CrmContract> contractRepository,
    SugarRepository<CrmPayment> paymentRepository)
    {
        _customerRepository = customerRepository;
        _contactRepository = contactRepository;
        _projectRepository = projectRepository;
        _codeRepository = codeRepository;
        _contractRepository = contractRepository;
        _paymentRepository = paymentRepository;
    }

    /// <summary>
    /// 客户数据汇总
    /// </summary>
    /// <returns></returns>
    public async Task<WorkCustomerTotal> GetCustomerTotalAsync()
    {
        var res = new WorkCustomerTotal()
        {
            CustomerCount = await _customerRepository.CountAsync(m=>true),
            ContractCount=await _contactRepository.CountAsync(m=>true),
            LeadCount=await _customerRepository.CountAsync(m=>m.Type==0),
            PoolCount = await _customerRepository.CountAsync(m=>m.Type==2)
        };
        return res;
    }
    
    /// <summary>
    /// 项目/商机数据汇总
    /// </summary>
    /// <returns></returns>
    public async Task<WorkProjectTotal> GetProjectTotalAsync()
    {
        var res = new WorkProjectTotal()
        {
            ChanceTotal = await _projectRepository.CountAsync(m=>m.ProjectType==CrmProjectTypeEnum.Opportunity),
            AllTotal=await _projectRepository.CountAsync(m=>true),
            ProceedTotal=await _projectRepository.CountAsync(m=>m.ProjectType==CrmProjectTypeEnum.Opportunity && m.OpportunityStatus==CrmOpportunityStatusEnum.InProgress),
            ProjectTotal = await _projectRepository.CountAsync(m=>m.ProjectType==CrmProjectTypeEnum.Project),
            Money=await _projectRepository.AsQueryable().Where(m=>m.ProjectType==CrmProjectTypeEnum.Project).SumAsync(m=>m.Amount)
        };
        return res;
    }

    /// <summary>
    /// 销售业绩趋势
    /// </summary>
    /// <returns></returns>
    public async Task<List<WorkProjectMonthMoney>> GetProjectMonthAsync()
    {
        var res = new List<WorkProjectMonthMoney>();
        var query=await _projectRepository.AsQueryable()
            .Where(m => m.CreateTime.Year==DateTime.Now.Year)
            .Select(m=>new
            {
                month=m.CreateTime.Month,
                amount=m.Amount
            })
            .MergeTable()
            .GroupBy(m=>new{m.month})
            .Select(m=>new
            {
                Month = m.month,
                Amount= SqlFunc.AggregateSum(m.amount)
            })
            .ToListAsync();
        for (var i = 1; i < 13; i++)
        {
            var model = query.FirstOrDefault(m=>m.Month==i);
            res.Add(new WorkProjectMonthMoney()
            {
                Month = i>9?i.ToString() : "0"+i,
                Amount = model?.Amount ?? 0
            });
        }
        return res;
    }

    /// <summary>
    /// 商机比例
    /// </summary>
    /// <returns></returns>
    public async Task<List<WorkKeyValue>> GetStageScaleAsync()
    {
        
        var query=await _projectRepository.AsQueryable()
            .Where(m => m.ProjectType==CrmProjectTypeEnum.Opportunity)
            .Select(m=>new
            {
                m.OpportunityStatus
            })
            .MergeTable()
            .GroupBy(m=>new{m.OpportunityStatus})
            .Select(m=>new
            {
                m.OpportunityStatus,
                Count= SqlFunc.AggregateCount(m.OpportunityStatus)
            })
            .ToListAsync();
        var res = new List<WorkKeyValue>();
        for (var i = 0; i < 6; i++)
        {
            var model = query.FirstOrDefault(m => m.OpportunityStatus ==(CrmOpportunityStatusEnum)i);
            res.Add(new WorkKeyValue()
            {
                Key = ((CrmOpportunityStatusEnum)i).GetDescription(),
                Value = model?.Count ?? 0
            });
        }
        return res;
    }
    
    /// <summary>
    /// 项目状态占比
    /// </summary>
    /// <returns></returns>
    public async Task<List<WorkKeyValue>> GetProjectStatusAsync()
    {
        
        var query=await _projectRepository.AsQueryable()
            .Where(m => m.ProjectType==CrmProjectTypeEnum.Project)
            .Select(m=>new
            {
                m.Status
            })
            .MergeTable()
            .GroupBy(m=>new{m.Status})
            .Select(m=>new
            {
                m.Status,
                Count= SqlFunc.AggregateCount(m.Status)
            })
            .ToListAsync();
        var res = new List<WorkKeyValue>();
        for (var i = 0; i < 4; i++)
        {
            var model = query.FirstOrDefault(m => m.Status ==(CrmProjectStatusEnum)i);
            res.Add(new WorkKeyValue()
            {
                Key = ((CrmProjectStatusEnum)i).GetDescription(),
                Value = model?.Count ?? 0
            });
        }
        return res;
    }
    
    /// <summary>
    /// 项目行业占比
    /// </summary>
    /// <returns></returns>
    public async Task<List<WorkKeyValue>> GetProjectIndustryAsync()
    {
        
        var query=await _projectRepository.AsQueryable()
            .Where(m => m.ProjectType==CrmProjectTypeEnum.Project)
            .Select(m=>new
            {
                Industry=SqlFunc.Subqueryable<CrmCustomer>().Where(s=>s.Id==m.CustomerId)
                    .Select(s=>s.Industry)
            })
            .MergeTable()
            .GroupBy(m=>new{m.Industry})
            .Select(m=>new
            {
                m.Industry,
                Count= SqlFunc.AggregateCount(m.Industry)
            })
            .ToListAsync();
        var res = new List<WorkKeyValue>();
        var hyList = await _codeRepository.GetListAsync(m => m.Tag == 3 && m.TypeId == 1589811762029531138);
        foreach (var item in hyList)
        {
            var model = query.FirstOrDefault(m => m.Industry==item.Id);
            res.Add(new WorkKeyValue()
            {
                Key = item.Name,
                Value = model?.Count ?? 0
            });
        }
        return res;
    }
    
    /// <summary>
    /// 商机金额分布
    /// </summary>
    /// <returns></returns>
    public async Task<List<WorkKeyAmount>> GetStageAmountAsync()
    {
        
        var query=await _projectRepository.AsQueryable()
            .Where(m => m.ProjectType==CrmProjectTypeEnum.Opportunity)
            .Select(m=>new
            {
                m.OpportunityStatus,
                m.Amount
            })
            .MergeTable()
            .GroupBy(m=>new{m.OpportunityStatus})
            .Select(m=>new
            {
                m.OpportunityStatus,
                Amount= SqlFunc.AggregateSum(m.Amount)
            })
            .ToListAsync();
        var res = new List<WorkKeyAmount>();
        for (var i = 0; i < 6; i++)
        {
            var model = query.FirstOrDefault(m => m.OpportunityStatus ==(CrmOpportunityStatusEnum)i);
            res.Add(new WorkKeyAmount()
            {
                Name = ((CrmOpportunityStatusEnum)i).GetDescription(),
                Amount = model?.Amount ?? 0
            });
        }
        return res;
    }
    
    /// <summary>
    /// 客户转换率
    /// </summary>
    /// <returns></returns>
    public async Task<WorkCrmConverScale> GetCustomerConverAsync()
    {
        var res = new WorkCrmConverScale()
        {
            CustomerCount = await _customerRepository.CountAsync(m=>true),
            StageCustomerCount=await _projectRepository.CountAsync(m=>m.ProjectType==CrmProjectTypeEnum.Opportunity),
            ContractCustomerCount=await _contractRepository.AsQueryable().GroupBy(m=>m.CustomerId).CountAsync(),
            PaymentCustomerCount = await _paymentRepository.AsQueryable().GroupBy(m=>m.CustomerId).CountAsync()
        };
        return res;
    }
}